import UIKit

// 主视图控制者
class ViewController: UIViewController, GameCallback {
    @IBOutlet weak private var mButtonMusic: UIButton!      // "播放音乐"按钮
    @IBOutlet weak private var mButtonPause: UIButton!      // "暂停"按钮
    private var mGame: Game!                                // 游戏
    @IBOutlet weak private var mLabelDifficulty: UILabel!   // "难度"标签
    @IBOutlet weak private var mLabelScore: UILabel!        // "得分"标签

    /**
     * "帮助"按钮的单击响应方法。
     */
    @IBAction private func onButtonHelpClicked() {
        if mGame.status == .PLAYING {
            self.onButtonPauseClicked()
        }

        let text = NSLocalizedString("IDS_HELP_TEXT", tableName: "Main", comment: "")
        let messageBox = UIAlertController(title: nil, message: text, preferredStyle: .alert)
        messageBox.addAction(UIAlertAction(title: "OK", style: .default))
        super.present(messageBox, animated: true)
    }

    /**
     * "音乐"按钮的单击响应方法。
     */
    @IBAction private func onButtonMusicClicked() {
        mButtonMusic.isSelected = mGame.playMusic()
    }
    
    /**
     * "暂停"按钮的单击响应方法。
     */
    @IBAction private func onButtonPauseClicked() {
        mGame.pause()
        mButtonPause.isSelected = mGame.status == .PAUSED
    }

    /**
     * "开始"按钮的单击响应方法。
     */
    @IBAction private func onButtonStartClicked() {
        // 游戏开始
        mGame.start()

        // 设置按钮状态
        mButtonPause.isEnabled = true
        mButtonPause.isSelected = false

        // 设置状态栏上的文字
        mLabelDifficulty.text = NSLocalizedString("IDS_DIFFICULTY", tableName: "Main", comment: "") + "1"
        mLabelScore.text = NSLocalizedString("IDS_SCORE", tableName: "Main", comment: "") + "0"
    }

    /**
     * 难度增加事件的响应方法。
     * @param difficulty    难度
     */
    internal func onDifficultyUp(_ difficulty: Int) {
        mLabelDifficulty.text = NSLocalizedString("IDS_DIFFICULTY", tableName: "Main", comment: "") + String(difficulty)
    }

    /**
     * 滑动手势的响应方法。
     * @param sender    事件发送者，即滑动手势
     */
    @IBAction private func onFling(_ sender: UISwipeGestureRecognizer) {
        mGame.onFling(sender.direction)
    }

    /**
     * 游戏结束事件的响应方法。
     * @param isWon 胜利则为 true，否则为 false
     */
    internal func onGameOver(_ isWon: Bool) {
        var text: String!
        if isWon {
            text = NSLocalizedString("IDS_WON", tableName: "Main", comment: "")
        } else {
            text = NSLocalizedString("IDS_LOST", tableName: "Main", comment: "")
        }
        Toast.makeText(view, text: text, duration: Toast.LENGTH_SHORT).show()

        mButtonPause.isEnabled = false
        mButtonPause.isSelected = false
    }
    
    /**
     * 视图不活动事件的响应方法。
     */
    @objc internal func onResignActive() {
        if mGame.status == .PLAYING {
            self.onButtonPauseClicked()
        }
    }

    /**
     * 得分事件的响应方法。
     * @param score 得分
     */
    internal func onScore(_ score: Int) {
        mLabelScore.text = NSLocalizedString("IDS_SCORE", tableName: "Main", comment: "") + String(score)
    }

    /**
     * 视图加载事件的响应方法。
     */
    internal override func viewDidLoad() {
        super.viewDidLoad()
        
        // 添加不活动事件监听者
        NotificationCenter.default.addObserver(self, selector: #selector(onResignActive), name: UIApplication.willResignActiveNotification, object: nil)

        // 获取控件
        let buttonStart = view.viewWithTag(Const.TAG_BUTTON_START)!
        let buttonHelp = view.viewWithTag(Const.TAG_BUTTON_HELP)!
        
        // 设置"暂停"按钮
        var image = UIImage(named: Const.BUTTON_PAUSE_PRESSED_IMAGE_FILE_NAME)!
        mButtonPause.setBackgroundImage(image, for: UIControl.State.selected)
        
        // 设置"播放音乐"按钮
        image = UIImage(named: Const.BUTTON_MUSIC_PRESSED_IMAGE_FILE_NAME)!
        mButtonMusic.setBackgroundImage(image, for: UIControl.State.selected)
        
        // 禁用 translatesAutoresizingMaskIntoConstraints，否则控件约束将无效
        buttonStart.translatesAutoresizingMaskIntoConstraints = false
        mButtonPause.translatesAutoresizingMaskIntoConstraints = false
        buttonHelp.translatesAutoresizingMaskIntoConstraints = false
        mLabelDifficulty.translatesAutoresizingMaskIntoConstraints = false
        mLabelScore.translatesAutoresizingMaskIntoConstraints = false
        mButtonMusic.translatesAutoresizingMaskIntoConstraints = false
        
        // 获取屏幕尺寸
        let screenY = UIApplication.shared.windows.first!.windowScene!.statusBarManager!.statusBarFrame.height
        let screenWidth = UIScreen.main.bounds.width
        let screenHeight = UIScreen.main.bounds.height - screenY

        // 计算格的尺寸
        Const.GRID_SIZE = screenWidth / Const.GAME_BOARD_GRID_COUNT_H

        // 计算按钮的尺寸和位置
        var btnSize = Const.GRID_SIZE * Const.SCALE_BUTTON_SIZE
        var btnX = Const.GRID_SIZE * Const.SCALE_PADDING_H
        if btnSize * Const.BUTTON_COUNT + btnX * (Const.BUTTON_COUNT + 1) > screenWidth {
            btnX = screenWidth / (Const.BUTTON_COUNT * 3 + 1)
            btnSize = btnX * 2
        }
        let btnY = screenY + Const.GRID_SIZE
        
        // 计算标签的尺寸
        let snakeBodyCount_V = (screenHeight - Const.GRID_SIZE * 2 - btnSize) / Const.GRID_SIZE
        let scale_label_height = snakeBodyCount_V - CGFloat(Int(snakeBodyCount_V)) + 1
        let lblDifficultyWidth = screenWidth * Const.SCALE_LABEL_DIFFICULTY_WIDTH
        let lblScoreWidth = screenWidth * Const.SCALE_LABEL_SCORE_WIDTH
        let lblHeight = Const.GRID_SIZE * scale_label_height
        
        // 设置标签的字体
        let font = UIFont.systemFont(ofSize: Const.GRID_SIZE * Const.SCALE_LABEL_TEXTSIZE)
        mLabelDifficulty.font = font
        mLabelScore.font = font
        
        // 计算游戏区域纵向的蛇身数
        Const.GAME_BOARD_GRID_COUNT_V = snakeBodyCount_V - scale_label_height
        
        // 添加控件约束
        /* "开始"按钮 */
        let lcButtonStartX = NSLayoutConstraint(item: buttonStart, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: btnX)
        view.addConstraint(lcButtonStartX)

        let lcButtonStartY = NSLayoutConstraint(item: buttonStart, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: btnY)
        view.addConstraint(lcButtonStartY)

        let lcButtonStartWidth = NSLayoutConstraint(item: buttonStart, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: btnSize)
        buttonStart.addConstraint(lcButtonStartWidth)

        let lcButtonStartHeight = NSLayoutConstraint(item: buttonStart, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: btnSize)
        buttonStart.addConstraint(lcButtonStartHeight)

        /* "暂停"按钮 */
        let lcButtonPauseX = NSLayoutConstraint(item: mButtonPause!, attribute: .left, relatedBy: .equal, toItem: buttonStart, attribute: .right, multiplier: 1.0, constant: btnX)
        view.addConstraint(lcButtonPauseX)

        let lcButtonPauseY = NSLayoutConstraint(item: mButtonPause!, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: btnY)
        view.addConstraint(lcButtonPauseY)

        let lcButtonPauseWidth = NSLayoutConstraint(item: mButtonPause!, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: btnSize)
        view.addConstraint(lcButtonPauseWidth)

        let lcButtonPauseHeight = NSLayoutConstraint(item: mButtonPause!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: btnSize)
        view.addConstraint(lcButtonPauseHeight)

        /* "音乐"按钮 */
        let lcButtonMusicX = NSLayoutConstraint(item: mButtonMusic!, attribute: .left, relatedBy: .equal, toItem: mButtonPause, attribute: .right, multiplier: 1.0, constant: btnX)
        view.addConstraint(lcButtonMusicX)

        let lcButtonMusicY = NSLayoutConstraint(item: mButtonMusic!, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: btnY)
        view.addConstraint(lcButtonMusicY)

        let lcButtonMusicWidth = NSLayoutConstraint(item: mButtonMusic!, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: btnSize)
        mButtonMusic.addConstraint(lcButtonMusicWidth)

        let lcButtonMusicHeight = NSLayoutConstraint(item: mButtonMusic!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: btnSize)
        mButtonMusic.addConstraint(lcButtonMusicHeight)

        /* "帮助"按钮 */
        let lcButtonHelpX = NSLayoutConstraint(item: buttonHelp, attribute: .left, relatedBy: .equal, toItem: mButtonMusic, attribute: .right, multiplier: 1.0, constant: btnX)
        view.addConstraint(lcButtonHelpX)

        let lcButtonHelpY = NSLayoutConstraint(item: buttonHelp, attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1.0, constant: btnY)
        view.addConstraint(lcButtonHelpY)

        let lcButtonHelpWidth = NSLayoutConstraint(item: buttonHelp, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: btnSize)
        buttonHelp.addConstraint(lcButtonHelpWidth)

        let lcButtonHelpHeight = NSLayoutConstraint(item: buttonHelp, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: btnSize)
        buttonHelp.addConstraint(lcButtonHelpHeight)

        /* "难度"标签 */
        let lcLabelDifficultyX = NSLayoutConstraint(item: mLabelDifficulty!, attribute: .left, relatedBy: .equal, toItem: view, attribute: .left, multiplier: 1.0, constant: 0)
        view.addConstraint(lcLabelDifficultyX)

        let lcLabelDifficultyY = NSLayoutConstraint(item: mLabelDifficulty!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0)
        view.addConstraint(lcLabelDifficultyY)

        let lcLabelDifficultyWidth = NSLayoutConstraint(item: mLabelDifficulty!, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: lblDifficultyWidth)
        mLabelDifficulty.addConstraint(lcLabelDifficultyWidth)

        let lcLabelDifficultyHeight = NSLayoutConstraint(item: mLabelDifficulty!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: lblHeight)
        mLabelDifficulty.addConstraint(lcLabelDifficultyHeight)

        /* "得分"标签 */
        let lcLabelScoreX = NSLayoutConstraint(item: mLabelScore!, attribute: .left, relatedBy: .equal, toItem: mLabelDifficulty, attribute: .right, multiplier: 1.0, constant: 0)
        view.addConstraint(lcLabelScoreX)

        let lcLabelScoreY = NSLayoutConstraint(item: mLabelScore!, attribute: .bottom, relatedBy: .equal, toItem: view, attribute: .bottom, multiplier: 1.0, constant: 0)
        view.addConstraint(lcLabelScoreY)

        let lcLabelScoreWidth = NSLayoutConstraint(item: mLabelScore!, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .width, multiplier: 1.0, constant: lblScoreWidth)
        mLabelScore.addConstraint(lcLabelScoreWidth)

        let lcLabelScoreHeight = NSLayoutConstraint(item: mLabelScore!, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .height, multiplier: 1.0, constant: lblHeight)
        mLabelScore.addConstraint(lcLabelScoreHeight)

        // 添加滑动手势支持
        let swipeGestureLeft = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.onFling))
        swipeGestureLeft.direction = .left
        view.addGestureRecognizer(swipeGestureLeft)

        let swipeGestureRight = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.onFling))
        swipeGestureRight.direction = .right
        view.addGestureRecognizer(swipeGestureRight)

        let swipeGestureUp = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.onFling))
        swipeGestureUp.direction = .up
        view.addGestureRecognizer(swipeGestureUp)

        let swipeGestureDown = UISwipeGestureRecognizer(target: self, action: #selector(ViewController.onFling))
        swipeGestureDown.direction = .down
        view.addGestureRecognizer(swipeGestureDown)
        
        // 创建游戏区域
        let gameBoardWidth = Const.GRID_SIZE * Const.GAME_BOARD_GRID_COUNT_H
        let gameBoardHeight = Const.GRID_SIZE * Const.GAME_BOARD_GRID_COUNT_V
        let gameBoardX = (screenWidth - gameBoardWidth) / 2
        let gameBoardY = btnY + btnSize + Const.GRID_SIZE * Const.SCALE_PADDING_H
        let gameBoard = GameBoard(frame: CGRect(x: gameBoardX, y: gameBoardY, width: gameBoardWidth, height: gameBoardHeight))
        view.addSubview(gameBoard)

        // 创建游戏
        mGame = Game(self, drawer: gameBoard.drawer, gameBoard: gameBoard)
    }
}
